#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <UIKit/UIKit.h>
#import <UIKit/UIApplication.h>
#import <EventKit/EventKit.h>
#import <LockInfo/Plugin.h>
#import <sqlite3.h>

#import "framework/FWCommon.h"
#import "framework/FWApplication.h"
#import "framework/FWDBAccess.h"
#import "framework/FWPreferences.h"

#import "PICommon.h"
#import "PIIntegration.h"
#import "PIContextObject.h"
#import "PIAlarm.h"
#import "PIPlugin.h"
#import "PIEventPlugin.h"

#import "PIEventIntegration202.h"
#import "PIEventIntegration250.h"
#import "PIEventIntegration.h"
#import "PIEventStatus.h"
#import "PIEventNative.h"
#import "PIEvent.h"
#import "PIAttendee.h"


static NSInteger const kSQLBasicEventList = 1;
static NSInteger const kSQLAddChildData = 2;
static NSInteger const kSQLAugmentedEvent = 3;
static NSInteger const kSQLAttendees = 4;
static NSInteger const kSQLAlarms = 5;
static NSInteger const kSQLNativeCalendars = 6;
static NSInteger const kSQLUUID = 7;


NSString* const kFieldNameEventStartDate = @"xxx_startdate";
NSString* const kFieldNameEventTagID = @"xxx_tagID";


@implementation PIEventIntegration


+ (PIEventIntegration*)implementationForApp:(FWApplication*)app
{
    PIPlugin* plugin = (PIPlugin*)app.fwPlugin;
    
    if (plugin.dbVersion == PIDatabaseVersion202)
        return [[[PIEventIntegration202 alloc] init] autorelease];
    if (plugin.dbVersion == PIDatabaseVersion250)
        return [[[PIEventIntegration250 alloc] init] autorelease];
    
    return nil;
}

// ******************************************************************************************
#pragma mark -
#pragma mark Fetch a list of basic events

+ (NSArray*)basicEventsList:(FWApplication*)application prefs:(FWPreferences*)prefs database:(FWDatabase*)database fromDate:(NSDate*)startDate toDate:(NSDate*)endDate
{
    // If PI not found then do nothing
    PIPlugin* plugin = (PIPlugin*)application.fwPlugin;
    if (!plugin.isPocketInformantPresent || plugin.isNativeOnly)
        return [NSArray array];

    PIEventIntegration* exec = [PIEventIntegration implementationForApp:application];
    NSMutableString* sql = [exec basicEventsListSQL:application prefs:prefs fromDate:startDate toDate:endDate];
    
    // Don't return calendars in the ignore list
    if (NSArray* calendars = [prefs arrayValue:kPIOptionsHiddenPIEventCalendars withDefault:nil]) {
        NSMutableString* ignoreCalendars = [NSMutableString stringWithCapacity:calendars.count * 3];
        for (NSString* calendar in calendars) {
            [ignoreCalendars appendString:calendar withSeparator:@","];
        }
        if (ignoreCalendars.length > 0)
            [sql appendFormat:@" and E.ZCALENDAR not in (%@)/*IgnoreCals*/", ignoreCalendars];
    }

    // Store the calendars we want the short versions of
    NSMutableDictionary* shortInfoCalendars = [NSMutableDictionary dictionaryWithCapacity:20];
    if (NSArray* calendars = [prefs arrayValue:kPIOptionsHideInfoPICalendars withDefault:nil]) {
        for (NSString* calendar in calendars) {
            [shortInfoCalendars setObject:calendar forKey:calendar];
        }
    }
    
    // Only return tags in the show list if we have one
    if ([prefs boolValue:kPIOptionsNoTagsFilter withDefault:kPIOptionsNoTagsFilterDefault]) {
        [sql appendFormat:@" and %@ is null/*SelectNoTags*/", kFieldNameEventTagID];
    }
    else if (NSArray* tags = [prefs arrayValue:kPIOptionsTagsFilters withDefault:nil]) {
        NSMutableString* selectTags = [NSMutableString stringWithCapacity:tags.count * 3];
        for (NSString* tag in tags) {
            [selectTags appendString:tag withSeparator:@","];
        }
        if (selectTags.length > 0)
            [sql appendFormat:@" and %@ in (%@)/*SelectTags*/", kFieldNameEventTagID, selectTags];
    }
    
    
    // Ensure the items are in our date range
    [sql appendFormat:@" and %@<=%i and E.ZENDDATEINTERNAL>=%i",
     kFieldNameEventStartDate,
     (int)[endDate timeIntervalSinceReferenceDate],
     (int)[startDate timeIntervalSinceReferenceDate]];
    
    
    // Since we are joining to the tags table we need to get back to a single record per event
    [sql appendString:@" group by E.Z_PK"];

    
    NSArray* results = FWDBGetRecordsFromConnection(sql, kSQLBasicEventList, [NSTimeZone systemTimeZone], database, application, exec, plugin.isDebugMode);

    // Only return results if we have some
    if (results)
        return results;
    else
        return [NSArray array];
}

- (NSObject*)sqlBasicEventList:(sqlite3_stmt*)sqlStatement timeZone:(NSTimeZone*)timezone
{
    NSInteger version = sqlite3_column_int(sqlStatement, 0);
    NSInteger key = sqlite3_column_int(sqlStatement, 1);
    NSString* title = FWDBReadColumnString(sqlStatement, 2);
    double cStart = sqlite3_column_double(sqlStatement, 3);
    double cEnd = sqlite3_column_double(sqlStatement, 5);
    NSString* location = FWDBReadColumnString(sqlStatement, 7);
    NSInteger allday = sqlite3_column_int(sqlStatement, 8);
    NSInteger busy = sqlite3_column_int(sqlStatement, 9);
    NSString* eventIcon = FWDBReadColumnString(sqlStatement, 10);
    NSInteger recurranceid = sqlite3_column_int(sqlStatement, 11);
    NSString* calendarName = FWDBReadColumnString(sqlStatement, 12);
    UIColor* calendarColor = FWDBReadColumnBlobWithDefault(sqlStatement, 13, [UIColor clearColor]);
    NSString* calendarIcon = FWDBReadColumnString(sqlStatement, 14);
    NSTimeZone* calendarTZ = FWDBReadColumnBlobWithDefault(sqlStatement, 15, timezone);
    NSInteger rootitem = sqlite3_column_int(sqlStatement, 16);
    NSInteger attendees = sqlite3_column_int(sqlStatement, 17);
    NSInteger itemVersion = sqlite3_column_int(sqlStatement, 18);

    NSTimeZone* cStartTZ = FWDBReadColumnBlobWithDefault(sqlStatement, 4, calendarTZ);
    NSTimeZone* cEndTZ = FWDBReadColumnBlobWithDefault(sqlStatement, 6, calendarTZ);

    NSDate* startDate = allday ? FWLocalDateForUTC([NSDate nullableDateWithTimeIntervalSinceReferenceDate:cStart]) : [NSDate nullableDateWithTimeIntervalSinceReferenceDate:cStart];
    NSDate* endDate = allday ? FWLocalDateForUTC([NSDate nullableDateWithTimeIntervalSinceReferenceDate:cEnd]) : [NSDate nullableDateWithTimeIntervalSinceReferenceDate:cEnd];
    
    PIEvent* event = [PIEvent piEventWithKey:[[NSNumber numberWithInt:key] stringValue]
                                     rootKey:[[NSNumber numberWithInt:rootitem] stringValue]
                                     version:itemVersion
                                       title:title
                                        icon:eventIcon
                                    location:location
                                   startDate:startDate
                           startDateTimeZone:cStartTZ
                                startDateRaw:cStart
                                     endDate:endDate
                             endDateTimeZone:cEndTZ
                                  endDateRaw:cEnd
                                      allDay:allday
                                    calendar:calendarName
                                calendarIcon:calendarIcon
                               calendarColor:calendarColor];

    event.hasAttendees = attendees > 0;
    event.repeating = recurranceid != 0;

    switch (busy) {
        case 0:
            event.availability = kPIEventAvailabilityBusy;
            break;
        case 1:
            event.availability = kPIEventAvailabilityFree;
            break;
        case 2:
            event.availability = kPIEventAvailabilityTentative;
            break;
        case 3:
            event.availability = kPIEventAvailabilityOutOfOffice;
            break;
        default:
            event.availability = kPIEventAvailabilityNotSupported;
            break;
    }
    
    return event;
}


// ******************************************************************************************
#pragma mark -
#pragma mark Add alarm data to PI events

+ (void)addAlarmDataToEventList:(FWApplication*)app database:(FWDatabase*)database events:(NSArray*)events prefs:(FWPreferences*)prefs
{
    // If PI not found then do nothing
    PIPlugin* plugin = (PIPlugin*)app.fwPlugin;
    if (!plugin.isPocketInformantPresent)
        return;
    
    
    // Get a list of keys
    NSMutableString* keys = [NSMutableString stringWithCapacity:50];
    NSMutableArray* lookups = [NSMutableArray arrayWithCapacity:events.count];
    for (PIEvent* event in events) {
        if (!event.isNative) {
            [keys appendString:event.rootKey withSeparator:@","];
            
            // Use short list of items for lookup later
            [lookups addObject:event];
        }
    }
    
    if (keys.length > 0) {
        PIEventIntegration* exec = [PIEventIntegration implementationForApp:app];
        NSString* alarmsSql = [exec addAlarmDataToEventListSQL:app keys:keys prefs:prefs];
    
        // Get a list of alarms for the events in ascending date order
        NSArray* alarms = FWDBGetSortedRecordsFromConnection(alarmsSql, kSQLAlarms, kFieldNameEventStartDate, database, app, exec, compareAlarmTimes, plugin.isDebugMode);

        NSDate* now = [NSDate date];
        for (PIAlarm* alarm in alarms) {
            if (NSArray* events = [lookups piEventsForRootKey:alarm.key]) {
                for (PIEvent* event in events) {
                    if (!event.alarms) {
                        event.alarms = [NSMutableArray arrayWithObject:alarm];
                        event.firstAlarm = alarm.date;
                        
                        // This is the next alarm if it hasn't yet expired
                        if ([alarm.date isEqualOrLaterThanDate:now])
                            event.nextAlarm = alarm.date;
                    }
                    else {
                        [(NSMutableArray*)event.alarms addObject:alarm];
                        
                        // This is the next alarm if it hasn't yet expired and we don't have an earlier alarm
                        if ((!event.nextAlarm || event.nextAlarm.isNull) && [alarm.date isEqualOrLaterThanDate:now])
                            event.nextAlarm = alarm.date;
                    }
                }
            }
        }
    }
}

- (NSObject*)sqlAlarms:(sqlite3_stmt*)sqlStatement context:(NSObject*)context
{
    NSInteger version = sqlite3_column_int(sqlStatement, 0);
    NSInteger key = sqlite3_column_int(sqlStatement, 1);
    NSInteger relative = sqlite3_column_int(sqlStatement, 2);
    NSInteger absolute = sqlite3_column_int(sqlStatement, 3);
    
    if (!context || (context == kFieldNameEventStartDate)) {
        double start = sqlite3_column_double(sqlStatement, 4);
        NSInteger allDay = sqlite3_column_int(sqlStatement, 5);
        
        if (allDay)
            context = FWLocalDateForUTC([NSDate nullableDateWithTimeIntervalSinceReferenceDate:start]);
        else
            context = [NSDate nullableDateWithTimeIntervalSinceReferenceDate:start];
    }
    
    if (relative != 0)
        return [PIAlarm alarmWithKey:[[NSNumber numberWithInt:key] stringValue]
                        relativeDate:-relative
                            baseDate:(NSDate*)context
                                type:kPIEventAlarmTypeNative];
    else
        return [PIAlarm alarmWithKey:[[NSNumber numberWithInt:key] stringValue]
                                date:[NSDate nullableDateWithTimeIntervalSinceReferenceDate:absolute]
                                type:kPIEventAlarmTypeNative];
}


+ (PIEvent*)augmentedBasicEvent:(PIEvent*)event application:(FWApplication*)app
{
    PIPlugin* plugin = (PIPlugin*)app.fwPlugin;

    PIEvent* augment = [[event copy] autorelease];
    augment.augmented = YES;
    
    PIEventIntegration* exec = [PIEventIntegration implementationForApp:app];
    FWDatabase* database = NULL;
    
    @try {
        database = FWDBConnectDatabase(app.databasePath, app);
        if (!database)
            return augment;
        
        NSString* augmentSql = [exec augmentedBasicEventSQL:event application:app];
        
        NSArray* info = FWDBGetRecordsFromConnection(augmentSql, kSQLAugmentedEvent, event.startDate, database, app, exec, plugin.isDebugMode);
        info = [info objectAtIndex:0];

        event.sensitivity = (PISensitivityType)[[info objectAtIndex:1] intValue];

        NSArray* tags = [info objectAtIndex:3];
        if (tags.count > 0) {
            NSMutableArray* newTags = [NSMutableArray arrayWithCapacity:tags.count];
            NSArray* allTags = [PIIntegration arrayOfTags:app keys:nil database:database];
            for (NSString* key in tags) {
                if (PIContextObject* tag = [allTags piContextObjectForKey:key.intValue])
                    [newTags addObject:tag];
            }
            if (newTags.count > 0) {
                [newTags sortUsingFunction:compareContextObjectNames context:nil];   
                augment.tags = newTags;
            }
        }
        
        NSString* notes = [info objectAtIndex:12];
        if (notes.length > 0)
            augment.notes = notes;
        
        if (event.isRepeating) {
            NSArray* daysOfMonth = [info objectAtIndex:4];
            NSMutableArray* daysOfWeek = [NSMutableArray arrayWithArray:[info objectAtIndex:5]];
            NSInteger firstDayOfWeek = [[info objectAtIndex:6] intValue];
            NSArray* monthsOfYear = [info objectAtIndex:7];
            NSDate* endDate = [info objectAtIndex:8];
            NSInteger occurances = [[info objectAtIndex:9] intValue];
            NSInteger interval = [[info objectAtIndex:10] intValue];
            NSInteger type = [[info objectAtIndex:11] intValue];
            
            augment.recurrance = [PIIntegration recurrenceWithFrequency:type
                                                               interval:interval
                                                          daysOfTheWeek:daysOfWeek
                                                         daysOfTheMonth:daysOfMonth
                                                        monthsOfTheYear:monthsOfYear
                                                             occurances:occurances
                                                                endDate:endDate
                                                               fromDate:PIRecurranceFromDateNone];
            
#ifdef DEBUG
            //                if (plugin.isDebugMode)
            //                    augment.notes = [NSString stringWithFormat:
            //                                     @"days of month = '%@'\n"
            //                                     "days of week = '%@'\n"
            //                                     "first day of week = %d\n"
            //                                     "months of year = '%@'\n"
            //                                     "end date = '%@'\n"
            //                                     "occurances = '%d'\n"
            //                                     "interval = '%d'\n"
            //                                     "type = '%d'\n"
            //                                     "------------------------\n"
            //                                     "%@",
            //                                     daysOfMonth,
            //                                     daysOfWeek,
            //                                     firstDayOfWeek,
            //                                     monthsOfYear,
            //                                     endDate,
            //                                     occurances,
            //                                     interval,
            //                                     type,
            //                                     augment.notes];
#endif
        }
        
        //augment.availability = (kPIEventAvailabilityType)[[info objectAtIndex:2] intValue];
        //augment.tags = [info objectAtIndex:3];
        
        NSString* attendeesSql = [exec attendeesSQL:event application:app];
        
        augment.attendees = FWDBGetSortedRecordsFromConnection(attendeesSql, kSQLAttendees, nil, database, app, exec, compareAttendees, plugin.isDebugMode);
        

//        NSString* alarmsSql = [NSString stringWithFormat:
//                               @"select a.id, a.relativetrigger, a.absolutetrigger"
//                               " from alarm a"
//                               " join itemalarmmap m on m.alarmid = a.id"
//                               " where m.itemid=%@",
//                               event.key];
//        
//        augment.alarms = FWDBGetRecordsFromConnection(alarmsSql, kSQLAlarms, event.startDate, database, app, exec);
        
        return augment;
    }
    @finally {
        FWDBDisconnectDatabase(database);
    }
}

- (NSObject*)sqlAugmentedEvent:(sqlite3_stmt*)sqlStatement
{
    NSInteger version = sqlite3_column_int(sqlStatement, 0);
    NSInteger status = sqlite3_column_int(sqlStatement, 1);
    NSInteger sensitivity = sqlite3_column_int(sqlStatement, 2);
    NSInteger busy = sqlite3_column_int(sqlStatement, 3);
    NSString* tags = FWDBReadColumnString(sqlStatement, 4);
    
    if (version == 1)
        return [NSArray arrayWithObjects:
                [NSNumber numberWithInt:status],
                [NSNumber numberWithInt:sensitivity],
                [NSNumber numberWithInt:busy],
                [tags componentsSeparatedByString:@","],
                nil];
    else {
        NSString* notes = FWDBReadColumnString(sqlStatement, 5);
        NSArray* daysOfMonth = FWDBReadColumnBlobToArray(sqlStatement, 6);
        NSArray* daysOfWeek = FWDBReadColumnBlobToArray(sqlStatement, 7);
        double endDate = sqlite3_column_double(sqlStatement, 8);
        NSInteger cFirstDayOfWeek = sqlite3_column_int(sqlStatement, 9);
        NSArray* monthsOfYear = FWDBReadColumnBlobToArray(sqlStatement, 10);
        NSInteger occurances = sqlite3_column_int(sqlStatement, 11);
        NSInteger interval = sqlite3_column_int(sqlStatement, 12);
        NSInteger type = sqlite3_column_int(sqlStatement, 13);

        NSString* locnTitle = FWDBReadColumnString(sqlStatement, 14);
        NSString* locnDescription = FWDBReadColumnString(sqlStatement, 15);
        double locnLat = FWDBReadColumnDoubleWithDefault(sqlStatement, 16, MAXFLOAT);
        double locnLong = FWDBReadColumnDoubleWithDefault(sqlStatement, 17, MAXFLOAT);

        return [NSArray arrayWithObjects:
                [NSNumber numberWithInt:status],
                [NSNumber numberWithInt:sensitivity],
                [NSNumber numberWithInt:busy],
                [tags componentsSeparatedByString:@","],
                daysOfMonth,
                daysOfWeek,
                [NSNumber numberWithInt:cFirstDayOfWeek],
                monthsOfYear,
                [NSDate dateWithTimeIntervalSinceReferenceDate:endDate],
                [NSNumber numberWithInt:occurances],
                [NSNumber numberWithInt:interval],
                [NSNumber numberWithInt:type],
                notes,
                locnTitle,
                locnDescription,
                [NSNumber numberWithDouble:locnLat],
                [NSNumber numberWithDouble:locnLong],
                nil];
    }
}

- (NSObject*)sqlAttendees:(sqlite3_stmt*)sqlStatement
{
    NSInteger version = sqlite3_column_int(sqlStatement, 0);
    NSString* commonName = FWDBReadColumnString(sqlStatement, 1);
    NSString* email = FWDBReadColumnString(sqlStatement, 2);
    NSInteger status = sqlite3_column_int(sqlStatement, 3);

    if ((commonName.length == 0) && (email.length > 0))
        commonName = email;
    
    return [PIAttendee attendeeWithName:commonName status:kPIParticipantStatusUnknown];
}


+ (NSDictionary*)nativeCalendarIcons:(FWApplication*)app database:(FWDatabase*)database calendars:(NSArray*)calendars
{
    PIPlugin* plugin = (PIPlugin*)app.fwPlugin;
    
    if (calendars.count == 0)
        return [NSDictionary dictionary];
    
    DebugLog(@"LI:PIEvent: Finding icons for native calendars");
    
    NSMutableDictionary* icons = [NSMutableDictionary dictionaryWithCapacity:calendars.count];
    
    PIEventIntegration* exec = [PIEventIntegration implementationForApp:app];
    NSString* augmentSql = @"select ZEXTERNALIDENTIFIER, ZEXTRADICTIONARY from ZEXTRADICTIONARYCONTAINER";
    NSArray* info = FWDBGetRecordsFromConnection(augmentSql, kSQLNativeCalendars, nil, database, app, exec, plugin.isDebugMode);

    DebugLog(@"LI:PIEvent: Found %d native calendars with extra info", info.count);

    if (info.count > 0) {
        for (NSArray* item in info) {
            NSString* key = [item objectAtIndex:0];
            if (![key hasPrefix:@"{"]) {
                if (NSString* icon = [[item objectAtIndex:1] objectForKey:@"iconString"])
                    [icons setObject:icon forKey:key];
            }
        }

        if (icons.count != info.count) {
            for (EKCalendar* calendar in calendars) {
                if (CGColorGetNumberOfComponents(calendar.CGColor) == 4) {
                    const CGFloat* colourElems = CGColorGetComponents(calendar.CGColor);
                    NSString* prefix = [NSString stringWithFormat:@"{title = %@; ", calendar.title];
                    NSString* suffix = [NSString stringWithFormat:
                                        @"; color = %.6f %.6f %.6f %.6f}", colourElems[0], colourElems[1], colourElems[2], colourElems[3]];
                    
                    for (NSArray* item in info) {
                        NSString* key = [item objectAtIndex:0];
                        if ([key hasPrefix:prefix] && [key hasSuffix:suffix]) {
                            DebugLog(@"LI:PIEvent: Found icon info for calendar %@", calendar.title);
                            NSDictionary* info = [item objectAtIndex:1];
                            if (NSString* icon = [info objectForKey:@"iconString"])
                                [icons setObject:icon forKey:FWKeyForCalendar(calendar)];
                            break;
                        }
                    }
                }
            }
        }
    }
    
    DebugLog(@"LI:PIEvent: Found icons %@", icons);

    return icons; 
}

+ (NSURL*)urlForShowEvent:(PIEvent*)event application:(FWApplication*)app
{
    XLog(@"LI:%@: Finding URL to access event via PI; event = %@", app.resourceName, event);
    
    // If PI not found then do nothing
    PIEventPlugin* plugin = (PIEventPlugin*)app.fwPlugin;

    NSURL* nativeURL = nil;
    if (event.isNative) {
        nativeURL = [PIEventNative urlForShowEvent:event application:app];
//        EKEventStore* eventStore = plugin.eventStore;
//        if (EKEvent* native = [eventStore eventWithIdentifier:event.rootKey]) {
//            if ([native respondsToSelector:@selector(externalURL)]) {
//                nativeURL = [native externalURL];
//                XLog(@"LI:%@: Native URL = %@", app.resourceName, nativeURL);
//            }
//        }
    }
    
    // Need at least 2.5 for direct event access
    if (plugin.dbVersion < PIDatabaseVersion250)
        return nativeURL;
    
    // Get the highest current task id
    PIEventIntegration* exec = [PIEventIntegration implementationForApp:app];
    NSString* sql = [NSString stringWithFormat:@"select Z_UUID, "
                     "(select Z_PK from ZPICALEVENT where Z_ENT=%@ and ZEXTERNALIDENTIFIER='%@') "
                     "from Z_METADATA where Z_VERSION = (select max(Z_VERSION) from Z_METADATA)",
                     DBEntityValue(plugin, kPIEntityTypeEventEK),
                     event.rootKey];
    
    // Get the uuid
    NSArray* results = FWDBGetRecords(sql, kSQLUUID, nil, app.databasePath, app, exec, plugin.isDebugMode);
    NSArray* info = [results objectAtIndex:0];
    NSString* uuid = [info objectAtIndex:0];
    NSString* nativeKey = [info objectAtIndex:1];
    
    if (event.isNative) {
        if (nativeKey.length > 0)
            return [NSURL URLWithString:[NSString stringWithFormat:@"informant://displayItem?%@",
                                         [PIIntegration urlForItemWithKey:[nativeKey intValue] type:kPIEntityTypeEventEK uuid:uuid]]];
        return nativeURL;
    }
    else {
        if ([event.key isEqualToString:event.rootKey]) 
            return [NSURL URLWithString:[NSString stringWithFormat:@"informant://displayItem?%@",
                                         [PIIntegration urlForItemWithKey:[event.key intValue] type:kPIEntityTypeEvent uuid:uuid]]];
        else
            return [NSURL URLWithString:[NSString stringWithFormat:@"informant://displayItem?%@",
                                         [PIIntegration urlForItemWithKey:[event.key intValue] type:kPIEntityTypeEventOccurance uuid:uuid]]];
    }
}    

+ (void)showInApplication:(PIEvent*)event application:(FWApplication*)app
{
    PIPlugin* plugin = (PIPlugin*)app.fwPlugin;
    NSURL* url = [PIEventIntegration urlForShowEvent:event application:app];
    
    NSLog(@"LI:%@: Displaying event: %@", app.resourceName, url);
    
    [plugin.liPlugin launchURL:url];
}

- (NSObject*)sqlUUID:(sqlite3_stmt*)sqlStatement
{
    NSString* uuid = FWDBReadColumnString(sqlStatement, 0);
    NSString* key = FWDBReadColumnString(sqlStatement, 1);
    return [NSArray arrayWithObjects:uuid, key, nil];
}

- (NSObject*)sqlNativeCalendarList:(sqlite3_stmt*)sqlStatement
{
    NSString* externName = FWDBReadColumnString(sqlStatement, 0);
    NSObject* info = FWDBReadColumnBlob(sqlStatement, 1);
    
    return [NSArray arrayWithObjects:externName, info, nil];
}


- (NSObject*)objectForSQLRecord:(sqlite3_stmt *)sqlStatement withId:(NSInteger)sqlid context:(NSObject*)context application:(FWApplication *)application
{
    if (sqlid == kSQLBasicEventList)
        return [self sqlBasicEventList:sqlStatement timeZone:(NSTimeZone*)context];
    else if (sqlid == kSQLAugmentedEvent)
        return [self sqlAugmentedEvent:sqlStatement];
    else if (sqlid == kSQLAttendees)
        return [self sqlAttendees:sqlStatement];
    else if (sqlid == kSQLAlarms)
        return [self sqlAlarms:sqlStatement context:context];
    else if (sqlid == kSQLNativeCalendars)
        return [self sqlNativeCalendarList:sqlStatement];
    else if (sqlid == kSQLUUID)
        return [self sqlUUID:sqlStatement];
    else
        return nil;
}

@end
